#import "FDGameView.h"

@implementation FDGameView
-(id)initWithFrame:(struct CGRect)frame {
	if ((self == [super initWithFrame: frame]) != nil) 
	{
		NSLog(@"GameView %s", _cmd);
		_contentRect = [UIHardware fullScreenApplicationContentRect];
		_offScreenRect = frame;
		_onScreenRect = frame;
		_onScreenRect.origin.x = 0.0f;

		defaults = [[FDDefaultsController alloc] init];
		
		float _clearColor[4] = {1, 1, 1, 0};
		float _whiteColor[4] = {1, 1, 1, .6};
				
		scoreCardView = [[FDScoreCardView alloc] initWithFrame:CGRectMake(3,frame.size.height-32,frame.size.width - 6,frame.size.height-32-95)];
		[self addSubview:scoreCardView];
		[scoreCardView setDelegate:self];
		[scoreCardView release];
		
		UIView	*bottomBar = [[UIView alloc] initWithFrame:CGRectMake(0,_onScreenRect.size.height-32,_onScreenRect.size.width,32.0f)];
		[bottomBar setImage:[UIImage applicationImageNamed:@"bottombar.png"]];
		[self addSubview:bottomBar];
		[bottomBar release];
		
		scoreLabel = [[UITextLabel alloc] initWithFrame:CGRectMake(230,4,90,24)];
		[scoreLabel setBackgroundColor: CGColorCreate( CGColorSpaceCreateDeviceRGB(), _clearColor)];
		[scoreLabel setColor: CGColorCreate( CGColorSpaceCreateDeviceRGB(), _whiteColor)];
		[scoreLabel setText:[NSString stringWithFormat:@"Score: %i",[scoreCardView grandtotal]]];
		//[scoreLabel setText:[NSString stringWithFormat:@"Score: 355"]];
		[bottomBar addSubview:scoreLabel];
		[scoreLabel release];
		
		turnsLabel = [[UITextLabel alloc] initWithFrame:CGRectMake(5,4,140,24)];
		[turnsLabel setBackgroundColor: CGColorCreate( CGColorSpaceCreateDeviceRGB(), _clearColor)];
		[turnsLabel setColor: CGColorCreate( CGColorSpaceCreateDeviceRGB(), _whiteColor)];
		[turnsLabel setText:[NSString stringWithFormat:@"Turns left: %i",13-[self turnCount]]];
		//[turnsLabel setText:[NSString stringWithFormat:@"Turns left: 0"]];
		[bottomBar addSubview:turnsLabel];
		[turnsLabel release];
		
		// This is the Dice Value Array used to speed up persistence saving when suspending
		pDiceValues = [[NSMutableArray alloc] init]; // Releases in dealloc
		
		[self draw5Dice];
	}
	return self;
}

#pragma mark Show and Hide Methods
- (void)show
{
	translate = [[UITransformAnimation alloc] initWithTarget:self];
	animator = [[UIAnimator alloc] init];

	struct CGAffineTransform trans = CGAffineTransformMakeTranslation(-_contentRect.size.width, 0);
	
	[self setFrame:_offScreenRect];
	[translate setStartTransform:CGAffineTransformMake(1,0,0,1,0,0)];
	[translate setEndTransform:trans];
	[animator addAnimation:translate withDuration:.5 start:YES];
	
	NSTimer		*animDelay = [NSTimer scheduledTimerWithTimeInterval:0.3
										  	  target:self
											selector:@selector(showScoreCardAfterDelay:)
											userInfo:nil
										 	 repeats:NO];
}

- (void)hide
{
	NSTimer		*animDelay = [NSTimer scheduledTimerWithTimeInterval:0.2
										  	  target:self
											selector:@selector(hideSelfAfterScoreCardDelay:)
											userInfo:nil
										 	 repeats:NO];
	
	[scoreCardView hide];
}

- (void)showScoreCardAfterDelay:(NSTimer *)aTimer
{
	[aTimer invalidate];
	[scoreCardView show];
}

- (void)hideSelfAfterScoreCardDelay:(NSTimer *)aTimer
{
	[aTimer invalidate];
	translate = [[UITransformAnimation alloc] initWithTarget:self];
	animator = [[UIAnimator alloc] init];
	
	struct CGAffineTransform trans = CGAffineTransformMakeTranslation(-_contentRect.size.width, 0);
	
	[self setFrame:_onScreenRect];
	[translate setStartTransform:trans];
	[translate setEndTransform:CGAffineTransformMake(1,0,0,1,0,0)];
	[animator addAnimation:translate withDuration:.5 start:YES];
}

#pragma mark Game Methods
-(void)newGame 
{
	fromLastPosition = NO;
	
	[scoreCardView clearScoreCard];
	[scoreCardView clearSelection:6];
	[scoreCardView setNewCard:YES];
	[scoreCardView scrollToTop];
	
	NSEnumerator *enumerator = [diceButtons objectEnumerator];
	FDDiePushButton *die;
		while ((die = [enumerator nextObject])) {
		[die newDie];
	}

	[self clearDieValues];
	[self setYahtzeeScratched:NO];
	[self setShouldClearHolds:YES];
	[self resetDice];
	[self resetRollCount];
	[self resetLastRoll];
	[self resetTurnCount];
	
	[delegate updateRollButtonWithLast:NO];

	// Bottom bar labels for Score and Turns	
	[scoreLabel setText:[NSString stringWithFormat:@"Score: %i",[scoreCardView grandtotal]]];
	[turnsLabel setText:[NSString stringWithFormat:@"Turns left: %i",13 - [self turnCount]]];
}

- (void)loadSavedGame
{
	fromLastPosition = YES;

	[scoreCardView loadSavedGame];
	
	NSArray	*temp = [[NSArray alloc] initWithArray:[defaults diceValues]];
	FDDiePushButton	*die;
	
	@try { // On occation, the dice values are cleared from the array stored in the defaults. In such a case, start a new game
		int	objectCount = [diceButtons count];
		int i;
		for(i = 0; i < objectCount; ++i)
		{
			die = [diceButtons objectAtIndex:i];
			[die setValue:[[temp objectAtIndex:i] intValue]];
		
			if ([self rollCount] >= 3) {
				[die setEnabled:NO];
			} else {
				[die setEnabled:YES];
			}
		}
		
		[temp release];	
		[self updateDiceValues];
		[delegate updateRollButtonWithLast:NO];
	}
	@catch (NSException *e) {
		NSLog(@"%s Caught and exception", _cmd);
		[self newGame];
		[delegate changeStateTo:NEWGAME];
	}
	@finally {
		
	}
	
	[scoreLabel setText:[NSString stringWithFormat:@"Score: %i",[scoreCardView grandtotal]]];
	[turnsLabel setText:[NSString stringWithFormat:@"Turns left: %i",13 - [self turnCount]]];
}

#pragma mark Dice Methods

- (void)draw5Dice // Draws the 5 dice for the first time on screen
{
	NSLog(@"%s", _cmd);
	diceButtons = [[NSMutableArray alloc] init];
//	[diceButtons retain]; // Is this needed? No, alloc init sets retain count to 1
	
	int i = 0;
	for(i = 0; i < 5; ++i)
	{
		[diceButtons addObject:[self diceButtonWithPosition:i]];
		[[diceButtons objectAtIndex:i] setEnabled:NO];
		[self addSubview:[diceButtons objectAtIndex:i]];
		[[diceButtons objectAtIndex:i] release]; // Release the button after adding it to the view
	}
}

- (FDDiePushButton *)diceButtonWithPosition:(int)pos // Returns a single die button
{
	FDDiePushButton	*button = [[FDDiePushButton alloc] initWithFrame:[self rectForDiePosition:pos]];
	[button addTarget:self action:@selector(dieSelected:) forEvents: (255)];
	// we release this above in draw5Dice after adding it to the superView
	return button;
}

- (struct CGRect)rectForDiePosition:(int)pos // These are the rects for where to draw the dice
{
	struct CGRect	diePosition;
	switch (pos) {
		case 0:
		diePosition = CGRectMake(0,12, 64, 71);
		break;
		case 1:
		diePosition = CGRectMake(64,12, 64, 71);
		break;
		case 2:
		diePosition = CGRectMake(128,12, 64, 71);
		break;
		case 3:
		diePosition = CGRectMake(192,12, 64, 71);
		break;
		case 4:
		diePosition = CGRectMake(256,12, 64, 71);
		break;
	}
	return diePosition;
}

- (void)dieSelected:(FDDiePushButton *)button // What to do when a die is selected
{
	if (![button isPressed]) {
		if (button == [diceButtons objectAtIndex:0]) {
			//NSLog(@"Button held: %i", 0);
			if (![button held]) [button setHeld:YES];
			else [button setHeld:NO];
		}
		if (button == [diceButtons objectAtIndex:1]) {
			//NSLog(@"Button held: %i", 1);
			if (![button held]) [button setHeld:YES];
			else [button setHeld:NO];
		}
		if (button == [diceButtons objectAtIndex:2]) {
			//NSLog(@"Button held: %i", 2);
			if (![button held]) [button setHeld:YES];
			else [button setHeld:NO];
		}
		if (button == [diceButtons objectAtIndex:3]) {
			//NSLog(@"Button held: %i", 3);
			if (![button held]) [button setHeld:YES];
			else [button setHeld:NO];
		}
		if (button == [diceButtons objectAtIndex:4]) {
			//NSLog(@"Button held: %i", 4);
			if (![button held]) [button setHeld:YES];
			else [button setHeld:NO];
		}
    }
}

- (void)clearHeldDice {
	NSLog(@"%s", _cmd);
	NSEnumerator *enumerator = [diceButtons objectEnumerator];
	FDDiePushButton *die;
	while ((die = [enumerator nextObject])) {
			[die setHeld:NO];
	}
}

- (void)resetDice {
	NSLog(@"%s", _cmd);
	//if ([self shouldClearHolds]) [self clearHeldDice];
	[self resetRollCount];
	[delegate updateRollButtonWithLast:NO];
}

- (void)updateDiceValues {
	NSLog(@"%s", _cmd);
	[self setDiceTotal:0];

	[pDiceValues removeAllObjects]; // Clear it out
	
	NSEnumerator *enumerator = [diceButtons objectEnumerator];
	FDDiePushButton *die;

	while ((die = [enumerator nextObject])) {		
		dieValues[[die value]] +=1;
		[pDiceValues addObject:[NSNumber numberWithInt:[die value]]];
		
		
		if (!fromLastPosition) {
			if (![self yahtzeeScratched]) {
				if (dieValues[[die value]] == 5) { // Change for testing 
					[self handleYahtzee];
				}
			}
		}
		[self setDiceTotal:[self diceTotal]+[die value]+1];
	}
}

- (void)clearDieValues {
	NSLog(@"%s", _cmd);
	int i = 0;
	for(i = 0; i < 6; ++i) {
		dieValues[i] = 0;
	}
	
	hasTwo = NO;
	hasThree = NO;
	hasFour = NO;
	hasFive = NO;
	hasSmStraight = NO;
	hasLgStraight = NO;
}

#pragma mark Rolling Methods
- (void)rollDice
{	
	NSLog(@"YAHTZEES %i", [scoreCardView yahtzeeCount]);
	[delegate changeStateTo:INGAME];
	fromLastPosition = NO;
	if ([self rollCount] >= 3 || [self rollCount] == 0) [self clearHeldDice];
	
	if ([self rollCount] == 0) {
		if ([scoreCardView selectedRow] <= 19) { // Hack, since selected row returns crazy number if no selection.
			[self resetDice];
			lastScore = 0;
			
			if ([scoreCardView newCard]) {
				[scoreCardView clearSelection:6];
			} else {
				[scoreCardView setInactiveRow:[scoreCardView selectedRow]];
			}
			
			[scoreCardView reloadData];
			if (wildcard) wildcard = NO; // Make sure you can't keep using the wildcard
			[self incrementTurn];
			[self clearDieValues];
		}
	}
	
	[self setRollCount:[self rollCount] + 1];

	NSEnumerator *enumerator = [diceButtons objectEnumerator];
	FDDiePushButton *die;
	while ((die = [enumerator nextObject])) {
		//NSLog(@"%s Enumerating through dice to roll: %i", _cmd, [die value] + 1);
		if (![die held]) [die roll];
				
		if ([self rollCount] >= 3) {
			[die setHeld:NO];
			[die setEnabled:NO];
		} else {
			[die setEnabled:YES];
		}
	}
	
	[delegate updateRollButtonWithLast:NO];

	// This gives the die a chance to animate. This ensures we get the last roll values
	NSTimer		*rollDelay = [NSTimer scheduledTimerWithTimeInterval:1.0
										  	  target:self
											selector:@selector(afterRollDelay:)
											userInfo:nil
										 	 repeats:NO];
}

- (void)afterRollDelay:(NSTimer *)aTimer
{
	NSLog(@"%s", _cmd);
//	[aTimer invalidate]; // If a timer is not set to repeat, it will automatically invalidate itself upon firing.
	[self clearDieValues]; // Clears out old values
	[self updateDiceValues]; // Updates them with the new roll results
	[scoreCardView setNewCard:NO]; // Moved from above the timer firing to test
}

#pragma mark Scoring
- (void)validateScoring {
	NSLog(@"%s", _cmd);
	int row = [scoreCardView selectedRow];
	
	if (lastScore >= 1) {
		[self clearLastRow];
	}
	
	int i = 0;
	
	NSLog(@"%s Row selected in main app: %i", _cmd, row);
	switch (row) {
			case ACES:
			[scoreCardView setAces:1*dieValues[0]];
			break;
			case TWOS:
			[scoreCardView setTwos:2*dieValues[1]];
			break;
			case THREES:
			[scoreCardView setThrees:3*dieValues[2]];
			break;
			case FOURS:
			[scoreCardView setFours:4*dieValues[3]];
			break;
			case FIVES:
			[scoreCardView setFives:5*dieValues[4]];
			break;
			case SIXES:
			[scoreCardView setSixes:6*dieValues[5]];
			break;
			case THREEOFAKIND:
				for(i = 0; i < 6; ++i) {
					if (dieValues[i] >= 3) {
						hasThree = YES;
					}
				}

				if (hasThree || wildcard) {
					[scoreCardView setThreeofakind:[self diceTotal]];
				} else {
					[scoreCardView setThreeofakind:0];
				}
			break;
			case FOUROFAKIND:
				for(i = 0; i < 6; ++i) {
					if (dieValues[i] >= 4) {
						hasFour = YES;
					}
				}
				if (hasFour || wildcard) {
					[scoreCardView setFourofakind:[self diceTotal]];
				} else {
					[scoreCardView setFourofakind:0];
				}
			break;
			case FULLHOUSE:
				for(i = 0; i < 6; ++i) {
					if (dieValues[i] == 2) {
						hasTwo = YES;
					}
				}
				for(i = 0; i < 6; ++i) {
					if (dieValues[i] == 3) {
						hasThree = YES;
					}
				}
				if ((hasTwo && hasThree) || wildcard) {
					[scoreCardView setFullhouse:25];
				} else {
					[scoreCardView setFullhouse:0];
				}
			break;
			case SMALLSTRAIGHT:
				if ((dieValues[0]>=1 && dieValues[1]>=1 && dieValues[2]>=1 && dieValues[3]>=1) ||
					(dieValues[1]>=1 && dieValues[2]>=1 && dieValues[3]>=1 && dieValues[4]>=1) ||
					(dieValues[2]>=1 && dieValues[3]>=1 && dieValues[4]>=1 && dieValues[5]>=1)) {
					hasSmStraight = YES;
				}

				if (hasSmStraight || wildcard) {
					[scoreCardView setSmallstraight:30];
				} else {
					[scoreCardView setSmallstraight:0];
				}
			break;
			case LARGESTRAIGHT:
				if ((dieValues[0]==1 && dieValues[1]==1 && dieValues[2]==1 && dieValues[3]==1 && dieValues[4]==1) ||
					(dieValues[1]==1 && dieValues[2]==1 && dieValues[3]==1 && dieValues[4]==1 && dieValues[5]==1)) {
					hasLgStraight = YES;
				}

				if (hasLgStraight || wildcard) {
					[scoreCardView setLargestraight:40];
				} else {
					[scoreCardView setLargestraight:0];
				}
			break;
			case YAHTZEE: 
				for(i = 0; i < 6; ++i) {
					if (dieValues[i] >= 5) { // Change for testing
						hasFive = YES;
					}
				}
				
				if (hasFive) {
					[scoreCardView setYahtzee:50];
				} else {
					[scoreCardView setYahtzee:0];
					[self setYahtzeeScratched:YES];
				}
			break;
			case CHANCE:
			[scoreCardView setChance:[self diceTotal]];
			break;
		}
				
		if (row == lastScore - 1) {
			[self setRollCount:[self lastRoll]];
			if ([self rollCount] <= 2) {
				[delegate updateRollButtonWithLast:YES];
			}
			
			[scoreCardView clearSelection:6]; // This should unselect the row by selecting something that does not show selection
			[self clearLastRow];
			[self setShouldClearHolds:NO];
			lastScore = -1;	
		} else {
			[delegate updateRollButtonWithLast:NO];
			[self setLastRoll:[self rollCount]];
			[self setShouldClearHolds:YES];
			[self resetDice];
			lastScore = row + 1;
		}
		
		[scoreCardView reloadData];
		[scoreLabel setText:[NSString stringWithFormat:@"Score: %i",[scoreCardView grandtotal]]];
		
		if ([self turnCount] >= 13){
			[self gameOver];
		}
}

- (void)handleYahtzee {
	NSLog(@"%i YAHTZEE", [scoreCardView yahtzeeCount]);
	NSString *bodyText;
	int y = 0;
	y = [scoreCardView yahtzeeCount];
	
	[scoreCardView setYahtzeeCount:y + 1];
	if ([scoreCardView yahtzeeCount]==1) {
		bodyText = [NSString stringWithFormat:@"Congradulations on your first yahtzee of the game."];
		[scoreCardView scrollToVisible:YAHTZEE];
	} else {
		bodyText = [NSString stringWithFormat:@"You have won a yahtzee chip. You may now place your score in any open position."];
	}
	
	UIAlertSheet	*alertSheet = [[UIAlertSheet alloc] initWithFrame:CGRectMake(0,240,320,240)];
	[alertSheet setTitle:@"Yahtzee!"];
	[alertSheet setContext:@"yahtzee"];
	[alertSheet setBodyText:bodyText];
	[alertSheet addButtonWithTitle:@"Ok"];
	[alertSheet setDelegate: self];
	[alertSheet popupAlertAnimated:YES];

	if ([scoreCardView yahtzeechips] >= 1) wildcard = YES;
	else wildcard = NO;
	// TODO: Place yahtzee chip on score card
}

#pragma mark Score Card Selection Stuff
- (void)clearLastRow { // Kludgy because of a stupid design decision early on.
	
	int row = lastScore - 1;
	
	NSLog(@"%s Row selected in main app: %i", _cmd, row);
	switch (row) {
			case ACES:
			[scoreCardView setAces:0];
			break;
			case TWOS:
			[scoreCardView setTwos:0];
			break;
			case THREES:
			[scoreCardView setThrees:0];
			break;
			case FOURS:
			[scoreCardView setFours:0];
			break;
			case FIVES:
			[scoreCardView setFives:0];
			break;
			case SIXES:
			[scoreCardView setSixes:0];
			break;
			case THREEOFAKIND:
			[scoreCardView setThreeofakind:0];
			break;
			case FOUROFAKIND:
			[scoreCardView setFourofakind:0];
			break;
			case FULLHOUSE:
			[scoreCardView setFullhouse:0];
			break;
			case SMALLSTRAIGHT:
			[scoreCardView setSmallstraight:0];
			break;
			case LARGESTRAIGHT:
			[scoreCardView setLargestraight:0];
			break;
			case YAHTZEE:
			[scoreCardView setYahtzee:0];
			break;
			case CHANCE:
			[scoreCardView setChance:0];
			break;
		}
		[delegate updateRollButtonWithLast:NO];
}

#pragma mark Turns
- (void)incrementTurn {
	// TODO: will need some modification for multiplayer
	NSLog(@"%s", _cmd);
	if ([self turnCount] >= 13) {
		[self gameOver];
	} else {
		[self setTurnCount:[self turnCount]+1];
		[turnsLabel setText:[NSString stringWithFormat:@"Turns left: %i",13-[self turnCount]]];
	}
}

- (void)gameOver {
	NSLog(@"%s Game Over", _cmd);
	[delegate changeStateTo:GAMEOVER];
	
	[delegate updateRollButtonWithLast:NO];
	NSString *bodyText;
	
	if ([defaults addedNewHighScore:[scoreCardView grandtotal] forName:[defaults playerOneName]]) {
		bodyText = [NSString stringWithFormat:@"You Scored %i!\nCongratulations! You've been added to the high scores list.",[scoreCardView grandtotal]];
	} else {
		bodyText = [NSString stringWithFormat:@"You Scored %i!\nYou need more practice.",[scoreCardView grandtotal]];
	}
	[defaults synchronize];
	
	
	UIAlertSheet	*alertSheet = [[UIAlertSheet alloc] initWithFrame:CGRectMake(0,240,320,240)];
	[alertSheet setTitle:@"Game Over!"];
	[alertSheet setContext:@"gameover"];
	[alertSheet setBodyText:bodyText];
	[alertSheet addButtonWithTitle:@"Play Again"];
	[alertSheet addButtonWithTitle:@"Cancel"];
	[alertSheet setDelegate: self];
	[alertSheet popupAlertAnimated:YES];
}

#pragma mark Counters
- (int)rollCount
{
	return rollCount;
}

- (void)setRollCount:(int)newRollCount
{
	rollCount = newRollCount;
}

- (void)resetRollCount
{
	[self setRollCount:0];
}

- (int)turnCount
{
	return turnCount;
}

- (void)setTurnCount:(int)newTurnCount
{
	turnCount = newTurnCount;
}

- (void)resetTurnCount
{
	[self setTurnCount:0];
}

- (int)lastRoll
{
	return lastRoll;
}

- (void)setLastRoll:(int)newLastRoll
{
	lastRoll = newLastRoll;
}

- (void)resetLastRoll
{
	[self setLastRoll:0];
}

- (int)diceTotal
{
	return diceTotal;
}

- (void)setDiceTotal:(int)newDiceTotal
{
	diceTotal = newDiceTotal;
}

#pragma mark Accessors

- (BOOL)shouldClearHolds
{
	return shouldClearHolds;
}

- (void)setShouldClearHolds:(BOOL)newShouldClearHolds
{
	shouldClearHolds = newShouldClearHolds;
}

- (BOOL)wildcard
{
	return wildcard;
}

- (void)setWildcard:(BOOL)newWildcard
{
	wildcard = newWildcard;
}

- (int)lastScore
{
	return lastScore;
}

- (void)setLastScore:(int)newLastScore
{
	lastScore = newLastScore;
}

- (NSMutableArray *)pDiceValues
{
	return pDiceValues;
}

- (BOOL)yahtzeeScratched
{
	return yahtzeeScratched;
}

- (void)setYahtzeeScratched:(BOOL)newYahtzeeScratched
{
	NSLog(@"%s %i", _cmd, newYahtzeeScratched);
	yahtzeeScratched = newYahtzeeScratched;
}

#pragma mark Score Card Accessors
- (int)selectedRow
{
	return [scoreCardView selectedRow];
}

- (void)setSelectedRow:(int)newRow
{
	[scoreCardView setSelectedRow:newRow];
}

- (int)yahtzeeCount
{
	return [scoreCardView yahtzeeCount];
}

- (void)setYahtzeeCount:(int)newYahtzeeCount
{
	[scoreCardView setYahtzeeCount:newYahtzeeCount];
}

- (NSArray *)scoreCardScores
{
	return [scoreCardView scoreCardScores];
}

- (NSArray *)scoreCardSetScores
{
	return [scoreCardView scoreCardSetScores];
}

#pragma mark Alert Handler
- (void)alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
	if ([[sheet context] isEqualToString:@"gameover"]) {
		
		if (button == 1) {
			[self newGame];
			[delegate changeStateTo:NEWGAME];
		}
		
		[self resetLastRoll];
		[self resetRollCount];
		
		[delegate updateRollButtonWithLast:NO];
	
	} else if ([[sheet context] isEqualToString:@"yahtzee"]) {

	}
	[sheet dismissAnimated:YES];
	[sheet release];// I think this is right, we have to release it at some point
}


#pragma mark Delegate
- (id)delegate
{
	return delegate;
}

- (void)setDelegate:(id)newDelegate
{
	delegate = newDelegate;
}

#pragma mark Dealloc
- (void)dealloc
{	
	[pDiceValues release];
	[diceButtons release];
	[animator release];
	[translate release];
	[defaults release];
	[super dealloc];
}

@end